home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / gnu_st.lha / gnu_st / smalltalk-1.1.1 / alloca.s < prev    next >
Text File  |  1991-09-12  |  8KB  |  312 lines

  1. /* `alloca' standard 4.2 subroutine for 68000's and 16000's and others.
  2.    Also has _setjmp and _longjmp for pyramids.
  3.    Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Emacs.
  6.  
  7. GNU Emacs is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY.  No author or distributor
  9. accepts responsibility to anyone for the consequences of using it
  10. or for whether it serves any particular purpose or works at all,
  11. unless he says so in writing.  Refer to the GNU Emacs General Public
  12. License for full details.
  13.  
  14. Everyone is granted permission to copy, modify and redistribute
  15. GNU Emacs, but only under the conditions described in the
  16. GNU Emacs General Public License.   A copy of this license is
  17. supposed to have been given to you along with GNU Emacs so you
  18. can know your rights and responsibilities.  It should be in a
  19. file named COPYING.  Among other things, the copyright notice
  20. and this notice must be preserved on all copies.  */
  21.  
  22.  
  23. /* Both 68000 systems I have run this on have had broken versions of alloca.
  24.    Also, I am told that non-berkeley systems do not have it at all.
  25.    So replace whatever system-provided alloca there may be
  26.    on all 68000 systems.  */
  27.  
  28. #define NOT_C_CODE
  29. #include "config.h"
  30.  
  31. #ifndef HAVE_ALLOCA  /* define this to use system's alloca */
  32.  
  33. #ifndef hp9000s300
  34. #ifndef m68k
  35. #ifndef m68000
  36. #ifndef WICAT
  37. #ifndef ns16000
  38. #ifndef sequent
  39. #ifndef pyramid
  40. #ifndef ATT3B5
  41. #ifndef XENIX
  42. you
  43. lose!!
  44. #endif /* XENIX */
  45. #endif /* ATT3B5 */
  46. #endif /* pyramid */
  47. #endif /* sequent */
  48. #endif /* ns16000 */
  49. #endif /* WICAT */
  50. #endif /* m68000 */
  51. #endif /* m68k */
  52. #endif /* hp9000s300 */
  53.  
  54.  
  55. #ifdef hp9000s300
  56. #ifdef OLD_HP_ASSEMBLER
  57.     data
  58.     text
  59.     globl    _alloca
  60. _alloca    
  61.     move.l    (sp)+,a0    ; pop return addr from top of stack
  62.     move.l    (sp)+,d0    ; pop size in bytes from top of stack
  63.     add.l    #ROUND,d0    ; round size up to long word
  64.     and.l    #MASK,d0    ; mask out lower two bits of size
  65.     sub.l    d0,sp        ; allocate by moving stack pointer
  66.     tst.b    PROBE(sp)    ; stack probe to allocate pages
  67.     move.l    sp,d0        ; return pointer
  68.     add.l    #-4,sp        ; new top of stack
  69.     jmp    (a0)        ; not a normal return
  70. MASK    equ    -4        ; Longword alignment
  71. ROUND    equ    3        ; ditto
  72. PROBE    equ    -128        ; safety buffer for C compiler scratch
  73.     data
  74. #else /* new hp assembler syntax */
  75. /*
  76.   The new compiler does "move.m <registers> (%sp)" to save registers,
  77.     so we must copy the saved registers when we mung the sp.
  78.   The old compiler did "move.m <register> <offset>(%a6)", which
  79.     gave us no trouble
  80.  */
  81.     text
  82.     set    PROBE,-128    # safety for C frame temporaries
  83.     set    MAXREG,22    # d2-d7, a2-a5, fp2-fp7 may have been saved
  84.     global    _alloca
  85. _alloca:
  86.     mov.l    (%sp)+,%a0    # return addess
  87.     mov.l    (%sp)+,%d0    # number of bytes to allocate
  88.     mov.l    %sp,%a1        # save old sp for register copy
  89.     mov.l    %sp,%d1        # compute new sp
  90.     sub.l    %d0,%d1        # space requested
  91.     and.l    &-4,%d1        # round down to longword
  92.     sub.l    &MAXREG*4,%d1    # space for saving registers
  93.     mov.l    %d1,%sp        # save new value of sp
  94.     tst.b    PROBE(%sp)    # create pages (sigh)
  95.     move.w    &MAXREG-1,%d0
  96. copy_regs_loop:            /* save caller's saved registers */
  97.     mov.l    (%a1)+,(%sp)+
  98.     dbra    %d0,copy_regs_loop
  99.     mov.l    %sp,%d0        # return value
  100.     mov.l    %d1,%sp
  101.     add.l    &-4,%sp        # adjust tos
  102.     jmp    (%a0)        # rts
  103. #endif /* new hp assembler */
  104. #else
  105. #ifdef m68k            /* SGS assembler totally different */
  106.     file    "alloca.s"
  107.     global    alloca
  108. alloca:
  109.     mov.l    (%sp)+,%a1    # pop return addr from top of stack
  110.     mov.l    (%sp)+,%d0    # pop size in bytes from top of stack
  111.     add.l    &R%1,%d0    # round size up to long word
  112.     and.l    &-4,%d0        # mask out lower two bits of size
  113.     sub.l    %d0,%sp        # allocate by moving stack pointer
  114.     tst.b    P%1(%sp)    # stack probe to allocate pages
  115.     mov.l    %sp,%a0        # return pointer as pointer
  116.     mov.l    %sp,%d0        # return pointer as int to avoid disaster
  117.     add.l    &-4,%sp        # new top of stack
  118.     jmp    (%a1)        # not a normal return
  119.     set    S%1,64        # safety factor for C compiler scratch
  120.     set    R%1,3+S%1    # add to size for rounding
  121.     set    P%1,-132    # probe this far below current top of stack
  122.  
  123. #else /* not m68k */
  124.  
  125. #ifdef m68000
  126.  
  127. #ifdef WICAT
  128. /*
  129.  * Registers are saved after the corresponding link so we have to explicitly
  130.  * move them to the top of the stack where they are expected to be.
  131.  * Since we do not know how many registers were saved in the calling function
  132.  * we must assume the maximum possible (d2-d7,a2-a5).  Hence, we end up
  133.  * wasting some space on the stack.
  134.  *
  135.  * The large probe (tst.b) attempts to make up for the fact that we have
  136.  * potentially used up the space that the caller probed for its own needs.
  137.  */
  138.     .procss m0
  139.     .config "68000 1"
  140.     .module    _alloca
  141. MAXREG:    .const    10
  142.     .sect    text
  143.     .global    _alloca
  144. _alloca:
  145.     move.l    (sp)+,a1    ; pop return address
  146.     move.l    (sp)+,d0    ; pop allocation size
  147.     move.l    sp,d1        ; get current SP value
  148.     sub.l    d0,d1        ; adjust to reflect required size...
  149.     sub.l    #MAXREG*4,d1    ; ...and space needed for registers
  150.     and.l    #-4,d1        ; backup to longword boundry
  151.     move.l    sp,a0        ; save old SP value for register copy
  152.     move.l    d1,sp        ; set the new SP value
  153.     tst.b    -4096(sp)    ; grab an extra page (to cover caller)
  154.     move.l    a2,d1        ; save callers register
  155.     move.l    sp,a2
  156.     move.w    #MAXREG-1,d0    ; # of longwords to copy
  157. loop:    move.l    (a0)+,(a2)+    ; copy registers...
  158.     dbra    d0,loop        ; ...til there are no more
  159.     move.l    a2,d0        ; end of register area is addr for new space
  160.     move.l    d1,a2        ; restore saved a2.
  161.     addq.l    #4,sp        ; caller will increment sp by 4 after return.
  162.     move.l    d0,a0        ; return value in both a0 and d0.
  163.     jmp    (a1)
  164.     .end    _alloca
  165. #else
  166.  
  167. /* Some systems want the _, some do not.  Win with both kinds.  */
  168. .globl    _alloca
  169. _alloca:
  170. .globl    alloca
  171. alloca:
  172.     movl    sp@+,a0
  173.     movl    a7,d0
  174.     subl    sp@,d0
  175.     andl    #~3,d0
  176.     movl    d0,sp
  177.     tstb    sp@(0)        /* Make stack pages exist  */
  178.                 /* Needed on certain systems
  179.                    that lack true demand paging */
  180.     addql    #4,d0
  181.     jmp    a0@
  182.  
  183. #endif /* not WICAT */
  184. #endif /* m68000 */
  185. #endif /* not m68k */
  186. #endif /* not hp9000s300 */
  187.  
  188. #ifdef ns16000
  189.  
  190.     .text
  191.     .align    2
  192. /* Some systems want the _, some do not.  Win with both kinds.  */
  193. .globl    _alloca
  194. _alloca:
  195. .globl    alloca
  196. alloca:
  197.  
  198. /* Two different assembler syntaxes are used for the same code
  199.     on different systems.  */
  200.  
  201. #ifdef sequent
  202. #define IM
  203. #define REGISTER(x) x
  204. #else
  205. #define IM $
  206. #define REGISTER(x) 0(x)
  207. #endif
  208.  
  209. /*
  210.  * The ns16000 is a little more difficult, need to copy regs.
  211.  * Also the code assumes direct linkage call sequence (no mod table crap).
  212.  * We have to copy registers, and therefore waste 32 bytes.
  213.  *
  214.  * Stack layout:
  215.  * new    sp ->    junk    
  216.  *         registers (copy)
  217.  *    r0 ->    new data        
  218.  *         |       (orig retval)
  219.  *         |      (orig arg)
  220.  * old  sp ->    regs      (orig)
  221.  *        local data
  222.  *    fp ->    old fp
  223.  */
  224.  
  225.     movd    tos,r1        /*  pop return addr */
  226.     negd    tos,r0        /*  pop amount to allocate */
  227.     sprd    sp,r2
  228.     addd    r2,r0
  229.     bicb    IM/**/3,r0    /*  4-byte align */
  230.     lprd    sp,r0
  231.     adjspb    IM/**/36    /*  space for regs, +4 for caller to pop */
  232.     movmd    0(r2),4(sp),IM/**/4    /*  copy regs */
  233.     movmd    0x10(r2),0x14(sp),IM/**/4
  234.     jump    REGISTER(r1)    /* funky return */
  235. #endif /* ns16000 */
  236.  
  237. #ifdef pyramid
  238.  
  239. .globl _alloca
  240.  
  241. _alloca: addw $3,pr0    # add 3 (dec) to first argument
  242.     bicw $3,pr0    # then clear its last 2 bits
  243.     subw pr0,sp    # subtract from SP the val in PR0
  244.     andw $-32,sp    # keep sp aligned on multiple of 32.
  245.     movw sp,pr0    # ret. current SP
  246.     ret
  247.  
  248. #ifdef PYRAMID_OLD /* This isn't needed in system version 4.  */
  249. .globl __longjmp
  250. .globl _longjmp
  251. .globl __setjmp
  252. .globl _setjmp
  253.  
  254. __longjmp: jump _longjmp
  255. __setjmp:  jump _setjmp
  256. #endif
  257.  
  258. #endif /* pyramid */
  259.  
  260. #ifdef ATT3B5
  261.  
  262.     .align 4
  263.     .globl alloca
  264.  
  265. alloca:
  266.     movw %ap, %r8
  267.     subw2 $9*4, %r8
  268.     movw 0(%r8), %r1    /* pc */
  269.     movw 4(%r8), %fp
  270.     movw 8(%r8), %sp
  271.     addw2 %r0, %sp /* make room */
  272.     movw %sp, %r0 /* return value */
  273.     jmp (%r1) /* continue... */
  274.  
  275. #endif /* ATT3B5 */
  276.  
  277. #ifdef XENIX
  278.  
  279. .386
  280.  
  281. _TEXT segment dword use32 public 'CODE'
  282. assume   cs:_TEXT
  283.  
  284. ;-------------------------------------------------------------------------
  285.  
  286. public _alloca
  287. _alloca proc near
  288.  
  289.     pop    ecx        ; return address
  290.     pop    eax        ; amount to alloc
  291.     add    eax,3        ; round it to 32-bit boundary
  292.     and    al,11111100B    ;
  293.     mov    edx,esp        ; current sp in edx
  294.     sub    edx,eax        ; lower the stack
  295.     xchg    esp,edx        ; start of allocation in esp, old sp in edx
  296.     mov    eax,esp        ; return ptr to base in eax
  297.     push    [edx+8]        ; save poss. stored reg. values (esi,edi,ebx)
  298.     push    [edx+4]        ;  on lowered stack
  299.     push    [edx]        ;
  300.     sub    esp,4        ; allow for 'add esp, 4'
  301.     jmp    ecx        ; jump to return address
  302.  
  303. _alloca endp
  304.  
  305. _TEXT    ends
  306.  
  307. end
  308.  
  309. #endif /* XENIX */
  310.  
  311. #endif /* not HAVE_ALLOCA */
  312.